<?php

/**
 * This file is part of the Framework03 PHP framework.
 * @author Walter Tamboer
 * @package Framework03
 */

abstract class FW_Controller_Action
{
    /**
     * @var FW_Controller_Dispatcher_Abstract The dispatcher used to process this action controller.
     */
    private $dispatcher;

    /**
     * Initializes a new instance of this class.
     * @param FW_Controller_Dispatcher_Abstract $dispatcher The dispatcher used to process this action controller.
     */
    public function __construct(FW_Controller_Dispatcher_Abstract $dispatcher)
    {
        $this->dispatcher = $dispatcher;
    }

    /**
     * Gets the dispatcher who processed this action controller.
     * @return FW_Controller_Dispatcher_Abstract Returns the dispatcher who processed this action controller.
     */
    public function getDispatcher()
    {
        return $this->dispatcher;
    }
	
	/**
	 * Gets the current request.
	 * @return FW_Controller_Request_Abstract
	 */
	public function getRequest()
	{
		return $this->getDispatcher()->getRequest();
	}

    /**
     * Does the actual dispatching of the action by calling the function on this class.
     * @param string $action The name of the action to dispatch.
     * @param array $arguments A list with arguments passed to the url.
     */
    final public function dispatch($action, array $arguments)
    {
        if (!method_exists($this, $action))
            throw new FW_Controller_Action_Exception(sprintf('Action "%s" does not exist.', $action), 404);

        $view = $this->$action($arguments);

        if ($view != null)
        {
            if (!($view instanceof FW_View_Abstract))
                throw new FW_Controller_Action_Exception(sprintf('View class returned from "%s" isn\'t based on FW_View_Abstract.', $action), 404);
    
            $view->render($this, $action);
        }
    }
    
    /**
     * Forwards the current action to the newly given action.
	 * @param string $action The name of the action.
	 * @param string $controller The name of the controller.
	 * @param array $options The additional options.
     */
    final protected function forward($action, $controller = null, array $options = array())
    {
        $request = $this->dispatcher->getRequest();

        if ($controller !== null)
            $request->setControllerName($controller);

        $request->setActionName($action)->setDispatched(false);
    }

    /**
     * Intercepting function calls that don't exist by throwing an exception.
     * @param string $name The name of the function that was called.
     * @param array $args The argument list.
     */
    public function __call($name, $args)
    {
        throw new FW_Controller_Action_Exception(sprintf('Method "%s" does not exist and was not trapped in __call()', $name), 500);
    }
}
